package com.xingchen.loveparttimejob.websocket;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xingchen.loveparttimejob.controller.MyCustomRuntimeException;
import com.xingchen.loveparttimejob.controller.servlet.MyConfigurator;
import com.xingchen.loveparttimejob.uitls.JWTUtils;

import com.xingchen.loveparttimejob.websocket.pojo.Message;
import jakarta.websocket.*;
import jakarta.websocket.server.ServerEndpoint;

import java.io.IOException;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author 小志
 * @date 2024/11/21 - 19:34
 */
@ServerEndpoint(value = "/ws/chat", configurator = MyConfigurator.class)
public class WebSocketChat {
    private static Map<String, Session> onlineMap = new ConcurrentHashMap<>();
    private String username; // 改为实例变量
    private static final ObjectMapper objectMapper = new ObjectMapper();
    @OnOpen
    public void onOpen(Session session, EndpointConfig config) {
        // 获取我们存储的token
        String authToken = (String) config.getUserProperties().get("Authentication");
        // 获取userId
        try {
            String userId = JWTUtils.generateJwtUtilsObject(authToken).getUserId();

            onlineMap.put(userId, session);
            username = userId; // 确保每个实例有一个唯一的username

            // 广播一条消息
            Set<String> keys = onlineMap.keySet();
            Message message = new Message("欢迎：" + userId + "进入群聊",0,username, null, true,keys);
            bulkSending(message);
            Message mess  = new Message("",2,username,username,false,null);
            bulkSending(mess);
            //需要打印所有用户的key出去进行显示
        } catch (MyCustomRuntimeException e) {
            // 如果JWT过期或其他异常，发送错误消息给客户端
            try {
                session.getBasicRemote().sendText("Error: " + e.getMessage());
//                session.close(); // 关闭session
            } catch (IOException ex) {
                throw new RuntimeException(ex);
            }
        }
    }

    @OnMessage
    public void onMessage(String message){
        System.out.println(message);
        try {
            Message messages = objectMapper.readValue(message, Message.class);
            messages.setUsername(username);
            System.out.println(messages.getUsername());
            bulkSending(messages);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }
    @OnClose
    public void onClose(){
        onlineMap.remove(username);
        Set<String> keys = onlineMap.keySet();
        Message message = new Message(username + "退出群聊", null, true,keys);
        bulkSending(message);
    }

    public void bulkSending(Message messages) {
        String json = "";
        try {
            json = objectMapper.writeValueAsString(messages);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }

        try {
            // 判断是系统消息还不是系统消息
            if (messages.isSystemMess()) {
                for (Session session : onlineMap.values()) {
                    if (session != null && session.isOpen()) {
                        session.getBasicRemote().sendText(json);
                    }
                }
            } else {
                if (messages.getToFrom() != null) {
                    // 私发消息
                    System.out.println(messages.toString());
                    int i=0;
                    for (String key : onlineMap.keySet()) {
                        if (key.equals(messages.getToFrom()) || key.equals(username)) {
                            System.out.println(++i);
                            onlineMap.get(key).getBasicRemote().sendText(json);
//                            break;
                        }
                    }
                } else {
                    // 群发
                    for (Session session : onlineMap.values()) {
                        if (session != null && session.isOpen()) {
                            session.getBasicRemote().sendText(json);
                        }
                    }
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
